﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace _16_多线程框架
{
    /// <summary>
    /// 自定义的线程状态
    /// </summary>
    public enum MyThreadState
    {
        /// <summary>
        /// 线程尚未启动
        /// </summary>
        NotStart = 0,
        /// <summary>
        /// 线程正在运行
        /// </summary>
        Running = 1,
        /// <summary>
        /// 线程挂起
        /// </summary>
        Suspended = 2,
        /// <summary>
        /// 线程已经停止
        /// </summary>
        Stopped = 3
    }
    /// <summary>
    /// 自定义线程类，用来进行线程操作
    /// </summary>
    public class ThreadClass
    {
        /// <summary>
        /// 线程名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 线程状态
        /// </summary>
        public MyThreadState State { get; set; }
        /// <summary>
        /// 线程类
        /// </summary>
        public Thread thread { get; set; }
        /// <summary>
        /// 当前进度条的进度
        /// </summary>
        public int Value { get; set; }
        /// <summary>
        /// 手动同步事件，用以提供阻塞线程的功能
        /// </summary>
        public ManualResetEvent manualResetEvent { get; set; }

        public event Action StartAndAbortEvent;//线程启动与终止的事件，WimForm界面做出对应的相应
        public event Action SuspendedAndResumeEvent;//线程挂起与唤醒的事件，WimForm界面做出对应的相应


        /// <summary>
        /// 运行是相应的事件：传入一个int类型的参数用于改变界面上的进度条与文本，返回一个int类型的参数用于获取界面设置的延时时间
        /// </summary>
        public event Func<int, int> RunEvent;//线程运行的事件，WimForm界面做出对应的相应

        /// <summary>
        /// 线程启动
        /// </summary>
        public void Start()
        {
            State = MyThreadState.Running;//标记线程状态为运行
            manualResetEvent = new ManualResetEvent(true);//默认为不阻塞状态
            thread = new Thread(DoWork);//实例化启动线程
            thread.IsBackground = true;//设置为后台线程
            thread.Start();//启动线程

            StartAndAbortEvent?.Invoke();//调用事件，界面做出相应
        }

        public void DoWork()
        {
            try
            {
                for (int i = 0; i <= 100; i++)
                {
                    Value = i;//记录下当前的值，用来标记当前的进度提供给后续的同步线程使用
                    manualResetEvent.WaitOne();//阻塞线程
                    int delay = RunEvent?.Invoke(i) ?? 10;  //更新界面的进度条与文本，然后获取界面设置的延时时间
                    Thread.Sleep(delay);//延时
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("线程异常:"+ex.ToString());
            }
            finally
            {
                State = MyThreadState.Stopped;//标记线程状态为停止
                StartAndAbortEvent?.Invoke();//调用事件，界面做出相应
            }
        }

        /// <summary>
        /// 线程终止
        /// </summary>
        public void Abort()
        {
            State = MyThreadState.Stopped;//标记线程状态为停止
            thread.Abort();//终止线程
            StartAndAbortEvent?.Invoke();//调用事件，界面做出相应
        }

        /// <summary>
        /// 线程挂起
        /// </summary>
        public void Suspend()
        {
            State = MyThreadState.Suspended;//标记线程状态为挂起
            manualResetEvent.Reset();//阻塞线程
            SuspendedAndResumeEvent?.Invoke();//调用事件，界面做出相应
        }
        /// <summary>
        /// 线程唤醒
        /// </summary>
        public void Resume()
        {
            State = MyThreadState.Running;//标记线程状态为运行
            manualResetEvent.Set();//解除阻塞
            SuspendedAndResumeEvent?.Invoke();//调用事件，界面做出相应
        }

    }
}
